////////////////////////////////////////////////////////////////////////////////
/*!	\file		c45.hpp
**	\brief		Declares the C45 class.
**	\author		Nate Cleveland
**	\date		11/14/2002 1:39:20 PM
**	\par		DESCRIPTION:
**				 The following assertions are made by the C45Tree.
**					- Attributes are always listed in the same order. 
**					- We never have missing or incomplete data.
**
**	\par		Tree Lingo...
**				 - A "Case" is a specific attribute that has been recieved from the 
**				 percept generators. In this tree these values are always continous.
**
**				 - A "Class" is the final decision that was made by the tree. For an
**				 AIUnit this is a true/false descision. If it is an Action Decision 
**				 Node it would be the AIUnit that the module choses to listen to.
**
**
**	\par		REMARKS:
**					
*/
////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "../AI_System.h"
#include "dTreeCommons.hpp"


namespace DTree
{
	//!minimum number of examples C45 trees need before they can learn
	extern const float C45_MIN_EXAMPLES;


	//forward declarations needed to compile the C45 class.
	class C45;
	class AIUnitAdapter;
	template<class RefObj_type, class Adapter_type>
		class C45Generator;

	////////////////////////////////////////////////////////////////////////////////
	/*!	\class		CaseExpander
	**	\brief		Used by node template class to find the floating point value of a
	**				 specific case.
	**	\author		Nate Cleveland
	**	\date		1/28/2003 1:56:32 PM
	**	\warning	none
	*/
	////////////////////////////////////////////////////////////////////////////////
	struct CaseExpander{float operator()(AI_System::AI_Attribute& att){return att.value;}};

	

	////////////////////////////////////////////////////////////////////////////////
	/*!	\class		C45
	**	\brief		Implements the C45 D-Tree module. Currently only supports AIUnits
	**				 but in the future it will use compile-time polymorphism (ie 
	**				 templitized class) to support ADNs aswell.
	**	\author		Nate Cleveland
	**	\date		11/14/2002 1:47:45 PM
	**	\warning	none
	*/
	////////////////////////////////////////////////////////////////////////////////
	class C45: public AI_System::AI_Unit
	{

	public:
		//!Short hand typedef for the type of Node used by this class.
		typedef Node<AI_System::AI_Attribute , bool, CaseExpander> C45Node;


		////////////////////////////////////////////////////////////////////////////////
		/*!	\class		AIUnitAdapter
		**	\brief		Fulfills the requirments of a C45Generator Adapter.
		**	\author		Nate Cleveland
		**	\date		11/22/2002 2:53:00 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		class AIUnitAdapter
		{
		public:
			//!All typedefs needed to fulfill the C45Generator requirments.
			typedef	C45							myRefClass;
			typedef bool						Class_type;
			typedef AI_System::AI_Attribute		Case_type;
			typedef AI_System::AI_ExampleUnit	Example_type;
			typedef C45Node						Node_type;

			//!Methods to fulfill the C45Generator requirments.
			static float		GetCaseValue(const Case_type& Case){return Case.value;}
			static Class_type	GetExampleResult(Example_type ex){return ex.result;}
			static Node_type&	GetTreeRootRef(myRefClass& myRef){return *(myRef.m_root);}
			static Node_type*	GetTreeRootPtr(myRefClass& myRef){return myRef.m_root;}
			static Node_type**	GetTreeRootPtrPtr(myRefClass& myRef){return &(myRef.m_root);}
			static Node_type*&	GetTreeRootPtrRef(myRefClass& myRef){return myRef.m_root;}
			static std::vector<Example_type>&	GetExampleVec(myRefClass &myRef){return myRef.trainingExamples;}
			static const std::vector<Case_type>&GetCaseVec(const Example_type& ex){return ex.attributes;}
		};

		//! Allow our generator class complete access to our data.
		friend AIUnitAdapter;	

		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Basic Ctor for C45 class.
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Sets members to zero. Nothing else.	
		**	\author		Nate Cleveland
		**	\date		11/14/2002 1:49:12 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		C45() throw();


		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Defualt dtor for C45 Tree.
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Frees the tree sturcture and clears out all examples.
		**	\author		Nate Cleveland
		**	\date		11/18/2002 3:12:24 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		~C45() throw();


		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Creates a deep copy of this object.
		**	\param		toCopyFrom		Reference to the object that we're to copying from.
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Creates a C45 object that is a copy of the given class. Calls the
		**				  parent's copy ctor.
		**	\author		Nate Cleveland
		**	\date		11/22/2002 3:57:52 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		C45(const C45& toCopyFrom) throw();
		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	DTree::C45::train()
		/*!	\brief		(Re)builds the decision tree with the current examples.
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Creates a C45Generator class to build the tree. Tree is built
		**				  with C45 methodology. At this time it does not prune the tree.
		**
		**	\author		Nate Cleveland
		**	\date		11/14/2002 12:48:08 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		virtual void train(void) throw();
		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	DTree::C45::save()
		/*!	\brief		Saves a tree to file.
		**	\param		none
		**	\return		Boolean value, false implies tree was not saved to file.
		**	\exception	none
		**	\author		Nate Cleveland
		**	\date		11/14/2002 12:48:08 PM
		**	\warning	Is not currently implemented.
		*/
		////////////////////////////////////////////////////////////////////////////////
		virtual bool save(void) throw();
		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	DTree::C45::load()
		/*!	\brief		Reads a tree (and examples) in from the file.
		**	\param		none
		**	\return		Boolean value, false implies tree was unable to load the file.
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/14/2002 12:52:24 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		virtual bool load() throw();
		
		
	protected:
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	DTree::C45::triggerAction()
		/*!	\brief		Returns true if we should trigger this action.
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Evaluates all the current Attributes (in DTree lingo these would
		**				 be known as "Cases") and decide whether or not to trigger this
		**				 action.
		**
		**	\author		Nate Cleveland
		**	\date		11/14/2002 12:54:01 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		virtual bool triggerAction(void) throw();	

		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Does nothing at this time...
		**	\param		none
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/14/2002 1:03:57 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		virtual void subClassInit(void){}
		C45Node*						m_root;			//!< Pntr to the tree root.
	};//end C45 class.

#if 1
	////////////////////////////////////////////////////////////////////////////////
	/*!	\class		C45_ADN
	**	\brief		Implements the C45 D-Tree module. Currently only supports AIUnits
	**				 but in the future it will use compile-time polymorphism (ie 
	**				 templitized class) to support ADNs aswell.
	**	\author		Nate Cleveland
	**	\date		11/14/2002 1:47:45 PM
	**	\warning	none
	*/
	////////////////////////////////////////////////////////////////////////////////
	class C45_ADN: public AI_System::AI_ADN
	{

	public:
		//!Short hand typedef for the type of Node used by this class.
		typedef Node<AI_System::AI_Attribute , AI_System::AI_ID, CaseExpander> C45_ADN_Node;


		////////////////////////////////////////////////////////////////////////////////
		/*!	\class		AIUnitAdapter
		**	\brief		Fulfills the requirments of a C45Generator Adapter.
		**	\author		Nate Cleveland
		**	\date		11/22/2002 2:53:00 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		class AIUnitAdapter
		{
		public:
			//!All typedefs needed to fulfill the C45Generator requirments.
			typedef	C45_ADN						myRefClass;
			typedef AI_System::AI_ID			Class_type;
			typedef AI_System::AI_Attribute		Case_type;
			typedef AI_System::AI_ExampleADN	Example_type;
			typedef C45_ADN_Node				Node_type;

			//!Methods to fulfill the C45Generator requirments.
			static float		GetCaseValue(const Case_type& Case){return Case.value;}
			static Class_type	GetExampleResult(Example_type ex){return ex.ID;}
			static Node_type&	GetTreeRootRef(myRefClass& myRef){return *(myRef.m_root);}
			static Node_type*	GetTreeRootPtr(myRefClass& myRef){return myRef.m_root;}
			static Node_type**	GetTreeRootPtrPtr(myRefClass& myRef){return &(myRef.m_root);}
			static Node_type*&	GetTreeRootPtrRef(myRefClass& myRef){return myRef.m_root;}
			static std::vector<Example_type>&	GetExampleVec(myRefClass &myRef){return myRef.trainingExamples;}
			static const std::vector<Case_type>&GetCaseVec(const Example_type& ex){return ex.attributes;}
		};

		//! Allow our generator class complete access to our data.
		friend AIUnitAdapter;	

		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Basic Ctor for C45_ADN class.
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Sets members to zero. Nothing else.	
		**	\author		Nate Cleveland
		**	\date		11/14/2002 1:49:12 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		C45_ADN() throw();


		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Defualt dtor for C45_ADN Tree.
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Frees the tree sturcture and clears out all examples.
		**	\author		Nate Cleveland
		**	\date		11/18/2002 3:12:24 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		~C45_ADN() throw();


		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Creates a deep copy of this object.
		**	\param		toCopyFrom		Reference to the object that we're to copying from.
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Creates a C45 object that is a copy of the given class. Calls the
		**				  parent's copy ctor.
		**	\author		Nate Cleveland
		**	\date		11/22/2002 3:57:52 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		C45_ADN(const C45_ADN& toCopyFrom) throw();
		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	DTree::C45::train()
		/*!	\brief		(Re)builds the decision tree with the current examples.
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Creates a C45Generator class to build the tree. Tree is built
		**				  with C45 methodology. At this time it does not prune the tree.
		**
		**	\author		Nate Cleveland
		**	\date		11/14/2002 12:48:08 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		virtual void train(void) throw();
		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	DTree::C45::save()
		/*!	\brief		Saves a tree to file.
		**	\param		none
		**	\return		Boolean value, false implies tree was not saved to file.
		**	\exception	none
		**	\author		Nate Cleveland
		**	\date		11/14/2002 12:48:08 PM
		**	\warning	Is not currently implemented.
		*/
		////////////////////////////////////////////////////////////////////////////////
		virtual bool save(void) throw();
		
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	DTree::C45::load()
		/*!	\brief		Reads a tree (and examples) in from the file.
		**	\param		none
		**	\return		Boolean value, false implies tree was unable to load the file.
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/14/2002 12:52:24 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		virtual bool load() throw();
		
		
	protected:
		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	DTree::C45_ADN::process()
		/*!	\brief		Returns true if we should trigger this action.
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**				 Evaluates all the current Attributes (in DTree lingo these would
		**				 be known as "Cases") and decide whether or not to trigger this
		**				 action.
		**
		**	\author		Nate Cleveland
		**	\date		11/14/2002 12:54:01 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		virtual AI_System::AI_ID process() throw();

		////////////////////////////////////////////////////////////////////////////////
		//	FUNCTION:	
		/*!	\brief		Does nothing at this time...
		**	\param		none
		**	\return		none
		**	\exception	none
		**	\par		DESCRIPTION:
		**					
		**	\author		Nate Cleveland
		**	\date		11/14/2002 1:03:57 PM
		**	\warning	none
		*/
		////////////////////////////////////////////////////////////////////////////////
		virtual void subClassInit(void){}
		C45_ADN_Node*						m_root;			//!< Pntr to the tree root.
	};//end C45 class.
#endif
}

